/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package otcapp.experto;

import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import otcapp.dto.InternoDTO;
import otcapp.dto.PiezaDTO;
import otcapp.dto.ResolucionDTO;
import otcapp.entidades.*;
import otcapp.experto.excepciones.ExpertoInternoException;
import otcapp.experto.excepciones.ExpertoPiezaException;
import otcapp.fabricas.FabricaExpertos;
import persistencia.exceptions.ExcepcionFachada;
import persistencia.Fachada;

/**
 *
 * @author diego
 */
public class ExpertoIngresarPieza extends Experto {
    
    private ExpertoConsultarPieza consultarPiezaExperto;
    private ExpertoConsultarInterno consultarInterno;
    
    public ExpertoIngresarPieza() {
        consultarPiezaExperto = (ExpertoConsultarPieza) FabricaExpertos.getInstancia().getExperto(FabricaExpertos.expertos.CONSULTAR_PIEZA);
        consultarInterno = (ExpertoConsultarInterno) FabricaExpertos.getInstancia().getExperto(FabricaExpertos.expertos.CONSULTAR_INTERNO);
    }

    /**
     * busca todos los Tipos de Piezas existentes
     *
     * @return Listado de todos los tipos de Piezas
     *
     */
    public List<TipoPieza> buscarTiposPiezas() {
        List<TipoPieza> tiposEncontrados;
        Criteria criterio = Fachada.getInstancia().crearCriterio(TipoPieza.class);
        criterio.addOrder(Order.asc("nombreTipo"));
        tiposEncontrados = Fachada.getInstancia().buscar(TipoPieza.class, criterio);
        return tiposEncontrados;
    }

    /**
     * Busca todos los Asuntos existentes en la Base de datos
     *
     * @return Listado de todos los Asuntos de piezas
     */
    public List<Asunto> buscarAsuntos() {
        List<Asunto> asuntosEncontrados;
        Criteria criterio = Fachada.getInstancia().crearCriterio(Asunto.class);
        criterio.addOrder(Order.asc("nombreAsunto"));
        asuntosEncontrados = Fachada.getInstancia().buscar(Asunto.class, criterio);
        return asuntosEncontrados;
    }

    /**
     * Busca todas las Oficinas existentes en la Base de datos
     *
     * @return Listado de Oficinas
     */
    public List<Oficina> buscarOficinas() {
        List<Oficina> oficinasEncontradas;
        Criteria criterio = Fachada.getInstancia().crearCriterio(Oficina.class);
        criterio.addOrder(Order.asc("nombreOficina"));
        oficinasEncontradas = Fachada.getInstancia().buscar(Oficina.class, criterio);
        return oficinasEncontradas;
    }

    /**
     * Busca todas las Ubicaciones existentes en la Base de datos
     *
     * @return Listado de Ubicaciones
     */
    public List<EstadoPieza> buscarUbicaciones() {
        List<EstadoPieza> ubicacionesEncontradas;
        Criteria criterio = Fachada.getInstancia().crearCriterio(EstadoPieza.class);
        criterio.addOrder(Order.asc("nombreUbicacion"));
        ubicacionesEncontradas = Fachada.getInstancia().buscar(Oficina.class, criterio);
        return ubicacionesEncontradas;
    }
    
    public List<Sede> buscarSedes() {
        List<Sede> sedesEncontradas;
        sedesEncontradas = Fachada.getInstancia().buscar(Sede.class, null);
        return sedesEncontradas;
    }
    
    public List buscarBeneficios(){
        return Fachada.getInstancia().buscar(Beneficio.class, null);
        
    }
    
    public List buscarResultadosResolucion(){
        return Fachada.getInstancia().buscar(ResultadoResolucion.class, null);
    }
    
    public List<InternoDTO> buscarInterno(InternoDTO dto) throws ExpertoPiezaException {
        try {
            return consultarInterno.buscarInterno(dto);
        } catch (ExpertoInternoException ex) {
            throw new ExpertoPiezaException(ex.getMessage());
        }
    }
    
    
    
    public PiezaDTO ingresarPieza(PiezaDTO dtoPieza) throws ExpertoPiezaException {
        
        validarPieza(dtoPieza);
        
        Pieza nuevaPieza;
        
        if (dtoPieza.getId() != null) {
            nuevaPieza = consultarPiezaExperto.buscarPiezaID(dtoPieza.getId());
        } else {
            nuevaPieza = crearPieza(dtoPieza.getTipo());
        }
        
        
        nuevaPieza.setAsuntos(dtoPieza.getAsuntos());
        nuevaPieza.setSede(dtoPieza.getSede());
        if (dtoPieza.getEmplazamientoDias().length() > 0) {
            nuevaPieza.setEmplazamientoDias(Integer.valueOf(dtoPieza.getEmplazamientoDias()));
        }
        if (dtoPieza.getEmplazamientoHoras().length() > 0) {
            nuevaPieza.setEmplazamientoHoras(Integer.valueOf(dtoPieza.getEmplazamientoHoras()));
        }
        nuevaPieza.setIdentificacionPieza(dtoPieza.getIdentificacion());
        nuevaPieza.setInterno(consultarInterno.buscarInternoXid(dtoPieza.getInterno().getId()));
        nuevaPieza.setObservacion(dtoPieza.getObservaciones());
        nuevaPieza.setOficinaDestino(dtoPieza.getDestinoPieza());
        nuevaPieza.setOficinaInicio(dtoPieza.getInicioPieza());
        nuevaPieza.setTipoPieza(dtoPieza.getTipo());
        //set ubicacion -> Lugar donde se encuentra
        if (dtoPieza.getId() == null) { //La pieza se ingresa por primera vez; hay que setear la ubicación
            setUbicacionPieza(nuevaPieza, buscarUbicacion(ubicacionEnum.MESA_ENTRADA), "Ingreso a Mesa de Entrada");
        }
        //Set fecha de entrada de la pieza
        nuevaPieza.setFechaEntrada(dtoPieza.getFechaEntrada());
        
        if(dtoPieza instanceof ResolucionDTO){
         ((Resolucion)nuevaPieza).setConclusiones(((ResolucionDTO)dtoPieza).getConclusiones());
        }
        
        if(nuevaPieza instanceof Expediente){
            ((Expediente)nuevaPieza).setNroExpediente(dtoPieza.getNroExpediente());
        }
        
        guardarPieza(nuevaPieza);
        
        dtoPieza.setUbicacion(nuevaPieza.getUbicacionActual().getNombreUbicacion());
        dtoPieza.setId(nuevaPieza.getId());
        dtoPieza.setDiasOTC(consultarPiezaExperto.calcularDiasPieza(nuevaPieza));
        dtoPieza.setFinalizada(nuevaPieza.isFinalizada());
        
        return dtoPieza;
        
    }
    
    public void darSalidaPieza(PiezaDTO dtoPieza) throws ExpertoPiezaException{
        
        Pieza pieza = consultarPiezaExperto.buscarPiezaID(dtoPieza.getId());
        
        pieza.setFechaSalida(dtoPieza.getFechaSalida());
        pieza.setOficinaDestino(dtoPieza.getDestinoPieza());
        pieza.setFinalizada(dtoPieza.isFinalizada());
        setUbicacionPieza(pieza, buscarUbicacion(ubicacionEnum.OFICINA_DESTINO), "Pieza envidada Oficina: "+pieza.getOficinaDestino().getNombreOficina());
        dtoPieza.setDiasOTC(consultarPiezaExperto.calcularDiasPieza(pieza));
        
        guardarPieza(pieza);
        
    }
    
    private void guardarPieza(Pieza pieza) throws ExpertoPiezaException {
        try {
            Fachada.getInstancia().guardar(pieza);
        } catch (ExcepcionFachada ex) {
            throw new ExpertoPiezaException("Error al guardar pieza: " + pieza.getIdentificacionPieza());
        }
    }
    
    private void validarPieza(PiezaDTO pieza) throws ExpertoPiezaException {
        if (pieza.getAsuntos() == null) {
            throw new ExpertoPiezaException("Debe seleccionar Asunto.");
        }
        
        if (pieza.getSede() == null) {
            throw new ExpertoPiezaException("Debe seleccionar Sede.");
        }
        
        if (pieza.getTipo() == null) {
            throw new ExpertoPiezaException("Debe seleccionar Tipo Pieza.");
        }
        
        if (pieza.getInterno() == null) {
            throw new ExpertoPiezaException("Debe seleccionar Interno.");
        }
        
        if (pieza.getIdentificacion().length() == 0) {
            throw new ExpertoPiezaException("Debe ingresar Identificación Pieza.");
        }
        
    }
    
    private Pieza crearPieza(TipoPieza tipo) {
        Pieza nuevaPieza;
        
        switch (tipo.getNombreTipo()) {
            case "Resolución":
                nuevaPieza = new Resolucion();
                break;
            case "Sentencia":
                nuevaPieza = new Sentencia();
                break;
            default:
                nuevaPieza = new Expediente();
                break;
        }
        
        return nuevaPieza;
    }
    
    public List buscarPiezas(PiezaDTO recogerDatosJDialogBuscar) throws ExpertoPiezaException {
        return consultarPiezaExperto.buscarPiezas(recogerDatosJDialogBuscar);
    }
    
    public List getHistorialSeguimientoPieza(Long idPieza) {
        return consultarPiezaExperto.getHistorialSeguimientoPieza(idPieza);
    }
    
    private enum ubicacionEnum {
        
        ARCHIVO, MESA_ENTRADA, OFICINA_TECNICA, OFICINA_ESTADISTICA, OFICINA_DESTINO, OTRA
    }
    
    private EstadoPieza buscarUbicacion(ubicacionEnum ubicacionNombre) {
        
        Criteria criterio = null;
        switch (ubicacionNombre) {
            case ARCHIVO:
                criterio = Fachada.getInstancia().crearCriterio(EstadoPieza.class);
                criterio.add(Restrictions.eq("nombreUbicacion", "Archivo"));
                break;
            case MESA_ENTRADA:
                criterio = Fachada.getInstancia().crearCriterio(EstadoPieza.class);
                criterio.add(Restrictions.eq("nombreUbicacion", "Mesa de Entrada"));
                break;
            case OFICINA_TECNICA:
                criterio = Fachada.getInstancia().crearCriterio(EstadoPieza.class);
                criterio.add(Restrictions.eq("nombreUbicacion", "Oficina Técnica"));
                break;
            case OFICINA_ESTADISTICA:
                criterio = Fachada.getInstancia().crearCriterio(EstadoPieza.class);
                criterio.add(Restrictions.eq("nombreUbicacion", "Oficina Control de Gestion y Estadística"));
                break;
            case OFICINA_DESTINO:
                criterio = Fachada.getInstancia().crearCriterio(EstadoPieza.class);
                criterio.add(Restrictions.eq("nombreUbicacion", "Oficina Destino"));
                break;
            case OTRA:
                criterio = Fachada.getInstancia().crearCriterio(EstadoPieza.class);
                criterio.add(Restrictions.eq("nombreUbicacion", "Otro"));
                break;
        }
        
        EstadoPieza ubicacion = (EstadoPieza) Fachada.getInstancia().buscar(EstadoPieza.class, criterio).get(0);
        return ubicacion;
        
    }
    
    public PiezaDTO setUbicacionPieza(PiezaDTO piezadto, EstadoPieza ubicacion, String observacion) throws ExpertoPiezaException {
        Pieza pieza = consultarPiezaExperto.buscarPiezaID(piezadto.getId());
        setUbicacionPieza(pieza, ubicacion, observacion);
        piezadto.setUbicacion(ubicacion.getNombreUbicacion());
        return piezadto;
    }
    
    private void setUbicacionPieza(Pieza pieza, EstadoPieza ubicacion, String observacion) throws ExpertoPiezaException {
        
        if (pieza.getHistorialSeguimiento() != null) {
            for (EstadoAsignado asignacionUbicacion : pieza.getHistorialSeguimiento()) {
                if (asignacionUbicacion.isUbicacionActual()) {
                    asignacionUbicacion.setUbicacionActual(Boolean.FALSE);
                }
            }
        }
        
        EstadoAsignado asignacionUbicacion = new EstadoAsignado();
        asignacionUbicacion.setUbicacionActual(Boolean.TRUE);
        asignacionUbicacion.setUbicacionAsignada(ubicacion);
        asignacionUbicacion.setFechaAsignacion(Fachada.getInstancia().getFecha());
        asignacionUbicacion.setObservaciones(observacion);
        
        pieza.addSeguimiento(asignacionUbicacion);
        
        guardarPieza(pieza);
        
    }
}
